package com.budwk.app.util.poiUtils;

import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.ImageData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.budwk.app.util.ExcelDeleteImage;
import com.budwk.app.util.poiUtils.excelPictureConfigBO.ExcelFileCreateParamBO;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.Units;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
 * @author ZY.Wang
 * @since 2023/7/31
 */
public class CustomImageModifyHandler implements CellWriteHandler {

    private short rowHeight = 55;

    private boolean fixedWidthFlag = false;

    // 重新填入的图片
    private List<ClientAnchor> clientAnchorList = new ArrayList<>();

    private static int dy2 = 644842;

    private int imgWidth = 210;

    public CustomImageModifyHandler(int rowHeight) {
        super();
        this.rowHeight = (short) rowHeight;
    }

    public CustomImageModifyHandler(int rowHeight, int imgWidth) {
        super();
        ExcelFileCreateParamBO excelFileCreateParamBO = new ExcelFileCreateParamBO();
        if (imgWidth != excelFileCreateParamBO.getImgWidth()) {
            this.fixedWidthFlag = true;
        }
        this.rowHeight = (short) rowHeight;
        this.imgWidth = imgWidth;
    }

    /**
     * 已经处理的Cell
     */
    private final CopyOnWriteArrayList<String> REPEATS = new CopyOnWriteArrayList<>();
    /**
     * 单元格的图片最大张数（每列的单元格图片张数不确定，单元格宽度需按照张数最多的长度来设置）
     */
    private final AtomicReference<Integer> MAX_IMAGE_SIZE = new AtomicReference<>(0);

    /**
     * 标记手动添加的图片，用于排除EasyExcel自动添加的图片
     */
    private final CopyOnWriteArrayList<Integer> CREATE_PIC_INDEX = new CopyOnWriteArrayList<>();

    private final AtomicInteger rowImageTotalWidth = new AtomicInteger(0);
    private final AtomicInteger preCellIndex = new AtomicInteger(0);

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer columnIndex, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
        //  在 数据转换成功后 不是头就把类型设置成空
        if (isHead) {
            return;
        }
        //将要插入图片的单元格的type设置为空,下面再填充图片
        if (CollectionUtils.isNotEmpty(cellData.getImageDataList())) {
            cellData.setType(CellDataTypeEnum.EMPTY);
        }
    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {

        if (cell.getColumnIndex() == 0) rowImageTotalWidth.set(0);

        //  在单元格写入完毕后 ，自己填充图片
        if (isHead || CollectionUtils.isEmpty(cellDataList)) {
            return;
        }
        boolean listFlag = false;
        Sheet sheet = cell.getSheet();
        // 此处为ExcelUrlConverterUtil的返回值
        List<ImageData> imageDataList = cellDataList.get(0).getImageDataList();

        if (CollectionUtils.isNotEmpty(imageDataList)) {
            listFlag = true;
        }
        if (!listFlag && imageDataList == null) {
            return;
        }
        String key = cell.getRowIndex() + "_" + cell.getColumnIndex();
        if (REPEATS.contains(key)) {
            return;
        }
        REPEATS.add(key);
        if (imageDataList.size() > MAX_IMAGE_SIZE.get()) {
            MAX_IMAGE_SIZE.set(imageDataList.size());
        }
        // 1英寸=72磅=25.4毫米=1440缇
        // 1磅=0.353毫米=20缇=4像素
        sheet.getRow(cell.getRowIndex()).setHeightInPoints((short) rowHeight);
        // sheet.setColumnWidth(cell.getColumnIndex(), listFlag ? 240 * 8 * MAX_IMAGE_SIZE.get() : 240 * 8);

        if (listFlag) {
            for (int i = 0; i < imageDataList.size(); i++) {
                ImageData imageData = imageDataList.get(i);
                if (imageData == null) {
                    continue;
                }
                byte[] image = imageData.getImage();
                this.insertImage(sheet, cell, image, i);
            }
        } else {
            this.insertImage(sheet, cell, imageDataList.get(0).getImage(), 0);
        }

        // 清除EasyExcel自动添加的没有格式的图片
        XSSFDrawing drawingPatriarch = (XSSFDrawing) sheet.getDrawingPatriarch();
        List<XSSFShape> shapes = drawingPatriarch.getShapes();
        for (int i = 0; i < shapes.size(); i++) {
            XSSFShape shape = shapes.get(i);
            if (shape instanceof XSSFPicture) {
                XSSFPicture picture = (XSSFPicture) shape;
                if (clientAnchorList.contains(picture.getClientAnchor())) continue;
                // 删除图片
                ExcelDeleteImage.deleteEmbeddedXSSFPicture(picture);
                ExcelDeleteImage.deleteCTAnchor(picture);
            }
        }
    }

    /**
     * 重新插入一个图片
     *
     * @param sheet       Excel页面
     * @param cell        表格元素
     * @param pictureData 图片数据
     * @param i           图片顺序
     */
    private void insertImage(Sheet sheet, Cell cell, byte[] pictureData, int i) {

        int columnIndex = cell.getColumnIndex();
        if (preCellIndex.get() != columnIndex) {
            preCellIndex.set(columnIndex);
            rowImageTotalWidth.set(0);
        }

        int index = sheet.getWorkbook().addPicture(pictureData, HSSFWorkbook.PICTURE_TYPE_PNG);

        UrlImageInfo urlImageInfo = new UrlImageInfo(pictureData);
        int picWidth = Units.pixelToEMU((int) (urlImageInfo.getTargetWidth() / 2.8));
        // wzy 2024-04-24 修改可以自定义excel宽和高，之前的宽和高是按照原图片等比放大或者缩小
        if (this.fixedWidthFlag) {
            urlImageInfo = new UrlImageInfo(pictureData, rowHeight, imgWidth);
            picWidth = Units.pixelToEMU((int) (urlImageInfo.getTargetWidth()));
        }

        Drawing<?> drawing = sheet.getDrawingPatriarch();
        if (drawing == null) {
            drawing = sheet.createDrawingPatriarch();
        }
        CreationHelper helper = sheet.getWorkbook().getCreationHelper();
        ClientAnchor anchor = helper.createClientAnchor();
        // 设置图片坐标
        final int borderWidth = Units.pixelToEMU(5);
        // 左上角
        anchor.setDx1(picWidth * i + borderWidth);
        anchor.setDx1(rowImageTotalWidth.get() + borderWidth);
        anchor.setDy1(borderWidth);
        // 右下角
        anchor.setDx2(picWidth + rowImageTotalWidth.get() - borderWidth);
        anchor.setDy2(-borderWidth);

        //设置图片行列
        anchor.setCol1(columnIndex);
        anchor.setCol2(columnIndex);
        int rowIndex = cell.getRowIndex();
        anchor.setRow1(rowIndex);
        anchor.setRow2(rowIndex + 1);
        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
        Picture picture = drawing.createPicture(anchor, index);

        // 该设置是解决删下一行数据，会把上一行图片删掉的问题
        picture.resize(0.99, 0.99);
        // 给SXSSFSheet类型提供正确的dy2  (XSSFShape类型的dy2是正确的)
        if (sheet instanceof XSSFShape) {
            dy2 = picture.getClientAnchor().getDy2();
        }
        // SXSSFSheet该类型需要重新设置dy2，不然图片会很小
        if (sheet instanceof SXSSFSheet) {
            picture.getPreferredSize().setDy2(dy2);
        }
        clientAnchorList.add(picture.getClientAnchor());

        rowImageTotalWidth.set(rowImageTotalWidth.get() + picWidth);
    }

//    private void insertImage(Sheet sheet, Cell cell, byte[] pictureData, int i) {
//
//        int columnIndex = cell.getColumnIndex();
//        if (preCellIndex.get() != columnIndex) {
//            preCellIndex.set(columnIndex);
//            rowImageTotalWidth.set(0);
//        }
//
//        int index = sheet.getWorkbook().addPicture(pictureData, HSSFWorkbook.PICTURE_TYPE_PNG);
//
//        UrlImageInfo urlImageInfo = new UrlImageInfo(pictureData, imgWidth, null);
//        int picWidth = Units.pixelToEMU((int) (urlImageInfo.getTargetWidth() / 2.8));
//
//        CREATE_PIC_INDEX.add(index);
//        Drawing<?> drawing = sheet.getDrawingPatriarch();
//        if (drawing == null) {
//            drawing = sheet.createDrawingPatriarch();
//        }
//        CreationHelper helper = sheet.getWorkbook().getCreationHelper();
//        ClientAnchor anchor = helper.createClientAnchor();
//        // 设置图片坐标
//        final int borderWidth = Units.pixelToEMU(5);
//        // 左上角
//        anchor.setDx1(picWidth * i + borderWidth);
//        anchor.setDx1(rowImageTotalWidth.get() + borderWidth);
//        anchor.setDy1(borderWidth);
//        // 右下角
//        anchor.setDx2(picWidth + rowImageTotalWidth.get() - borderWidth);
//        anchor.setDy2(-borderWidth);
//
//        //设置图片行列
//        anchor.setCol1(columnIndex);
//        anchor.setCol2(columnIndex);
//        int rowIndex = cell.getRowIndex();
//        anchor.setRow1(rowIndex);
//        anchor.setRow2(rowIndex + 1);
//        //anchor.setAnchorType(ClientAnchor.AnchorType.DONT_MOVE_AND_RESIZE);
//        anchor.setAnchorType(ClientAnchor.AnchorType.MOVE_AND_RESIZE);
//        Picture picture = drawing.createPicture(anchor, index);
//
//        // 该设置是解决删下一行数据，会把上一行图片删掉的问题
//        picture.resize(0.99,0.99);
//        // 给SXSSFSheet类型提供正确的dy2  (XSSFShape类型的dy2是正确的)
//        if (sheet instanceof XSSFShape) {
//            dy2 = picture.getClientAnchor().getDy2();
//        }
//        // SXSSFSheet该类型需要重新设置dy2，不然图片会很小
//        if (sheet instanceof SXSSFSheet) {
//            picture.getPreferredSize().setDy2(dy2);
//        }
//        clientAnchorList.add(picture.getClientAnchor());
//
//        rowImageTotalWidth.set(rowImageTotalWidth.get() + picWidth);
//    }
}
